/**
  ******************************************************************************
  * @file    can_bootloader.c
  * $Author: wdluo $
  * $Revision: 17 $
  * $Date:: 2012-07-06 11:16:48 +0800 #$
  * @brief   基于CAN总线的Bootloader程序.
  ******************************************************************************
  * @attention
  *
  *<h3><center>&copy; Copyright 2009-2012, ViewTool</center>
  *<center><a href="http:\\www.viewtool.com">http://www.viewtool.com</a></center>
  *<center>All Rights Reserved</center></h3>
  * 
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdio.h>
#include "system_init.h"
#include "ChipMessageApi.h"
#include "Flash.h"
#include "can_boot.h"
#include "Flash.h"
#if ENCRYPT
#include "aes.h"
#endif
/* Private typedef -----------------------------------------------------------*/
typedef  void (*pFunction)(void);

/* Private define ------------------------------------------------------------*/

/* Base address of the Flash sectors */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/**
 * @brief  获取固件升级标志
 * @return 固件升级标志状态
 * @retval 1 固件升级标志有效
 * @retval 0 固件升级标志无效
 */
uint8_t CAN_BOOT_GetProgRequest(void)
{
  //读取请求固件升级标志，需要自己实现
  if(*((uint32_t *)BOOT_REQ_FLAG_ADDR)==BOOT_REQ_FLAG){
    return 1;
  }else{
    return 0;
  }
}
/**
 * @brief  将固件升级标志置位
 */
void CAN_BOOT_SetProgRequest(void)
{
	uint32_t FlashRetVal;
	uint32_t AppValidFlag = 0xFFFFFFFF;
	FlashRetVal = FlashEEWriteNBytes(APP_VALID_FLAG_ADDR, 4, (uint8_t *)(&AppValidFlag));
	if(FlashRetVal != CMD_SUCCESS)
	{
		printf("CAN_BOOT_SetProgRequest failed\r\n");
	}
	uint32_t BootReqFlag = BOOT_REQ_FLAG;
	FlashRetVal = FlashEEWriteNBytes(BOOT_REQ_FLAG_ADDR, 4, (uint8_t *)(&BootReqFlag));
	if(FlashRetVal != CMD_SUCCESS)
	{
		printf("CAN_BOOT_SetProgRequest failed\r\n");
	}
}

/**
 * @brief  将固件升级标志复位
 */
void CAN_BOOT_ResetProgRequest(void)
{
	uint32_t FlashRetVal;
	uint32_t BootReqFlag = 0xFFFFFFFF;
	FlashRetVal = FlashEEWriteNBytes(BOOT_REQ_FLAG_ADDR, 4, (uint8_t *)(&BootReqFlag));
	if(FlashRetVal != CMD_SUCCESS)
	{
		printf("CAN_BOOT_SetProgRequest failed\r\n");
	}
}

/**
 * @brief  将固件升级标志置位
 */
void CAN_BOOT_SetAppValid(void)
{
	uint32_t FlashRetVal;
	uint32_t AppValidFlag = APP_VALID_FLAG;
	FlashRetVal = FlashEEWriteNBytes(APP_VALID_FLAG_ADDR, 4, (uint8_t *)(&AppValidFlag));
	if(FlashRetVal != CMD_SUCCESS)
	{
		printf("CAN_BOOT_SetAppValid failed\r\n");
	}
}

/**
 * @brief 软件复位程序
 */
void CAN_BOOT_Reset(void)
{
	asm("RESET");
}

void __set_MSP(uint32_t value){
	asm(" MOV SP,%0 \n": :"r"(value): "sp");
}
/**
 * @brief 执行APP程序
 */
void CAN_BOOT_ExeApp(void)
{
	typedef  void (*pFunction)(void); //定义void函数指针类型，
	uint32_t JumpAddress = *(volatile uint32_t*) (APP_START_ADDR + 4); //获取APP的startup()入口地址;
	pFunction Jump_To_Application = (pFunction) JumpAddress; //它可以接受任何类型函数的赋值
	printf("Go to APP!\r\n");
	SYS_VECTOFF = APP_START_ADDR ; //设置向量表偏移值，即重映射向量表，这对中断服务函数正确执行至关重要
	__set_MSP(*(uint32_t*) APP_START_ADDR);
	Jump_To_Application(); //使用新的函数指针，转向执行APP的startup()函数，这将导致APP程序启动
}
/**
 * @brief 擦除应用程序
 * @return 擦除状态
 * @retval 0 成功
 * @retval 1 失败
 */
uint8_t CAN_BOOT_EraseApp(void)
{
  return 0;
}

/**
 * @brief 判断APP应用程序是否有效
 * @return 应用程序有效状态
 * @retval 0 无效
 * @retval 1 有效
 */
uint8_t CAN_BOOT_CheckApp(void)
{
  return 1;
}

/**
 * @brief  将数据写入Flash
 * @param  Addr 数据起始地址
 * @param  pData 数据指针
 * @param  DataLen 写入数据字节数
 * @return 写入状态
 * @retval 0 成功
 * @retval 1 失败
 */
uint8_t CAN_BOOT_WriteDataToFlash(uint32_t Addr,uint8_t *pData,uint32_t DataLen)
{
	uint32_t ret = FlashWriteNKBytes(Addr, 1024, pData);
	return ret;
}



